namespace hjc {
	export class TimeManager extends Singleton implements ILaunchable {
		private $pastFrame: number = 0;
		private $pastTime: number = 0;
		private $registers: Register[] = [];

		public get pastFrame(): number { return this.$pastFrame; }
		public get pastTime(): number { return this.$pastTime; }
		public get pastSeconds(): number { return Math.ceil(this.$pastTime / 1000); }
		public launch(options: LaunchOptions): TimeManager {
			egret.startTick(pastTime => {
				this.$pastTime = pastTime;
				this._onFrame();
				return false;
			}, this);
			return this;
		}

		private _onFrame(): void {
			this.$pastFrame++;
			for (let register of this.$registers) {
				if (this.$pastFrame % register.every === 0) {
					if (register.context instanceof System && !register.context.enabled) return;
					register.times++;
					utils.call(register.notified, register.context, { pastTime: this.$pastTime, times: register.times });
				}
			}
		}

		//取消所有回调
		public stop() {
			egret.stopTick(passTime => { this._onFrame(); return false; }, this);
		}

		//以多少帧一次注册回调
		public registerByFrames(frames: number, notified: (param?: TimeParam) => any, context?: any): void {
			if (!isFunc(notified)) { hjc.warn('time notified must be a funciton.'); return; }
			this.$registers.push({ every: Math.round(frames * 60 / ui.getStage().frameRate), notified, context, times: 0 });
		}

		//以每秒钟多少次注册回调
		public registerByTimesSecond(times: number, notified: (param?: TimeParam) => any, context?: any): void {
			if (!isFunc(notified)) { hjc.warn('time notified must be a funciton.'); return; }
			this.$registers.push({ every: Math.round(60 / times), notified, context, times: 0 });
		}

		//以N秒钟注册回调
		public registerBySeconds(seconds: number, notified: (param?: TimeParam) => any, context?: any): void {
			if (!isFunc(notified)) { hjc.warn('time notified must be a funciton.'); return; }
			this.$registers.push({ every: Math.round(60 * seconds), notified, context, times: 0 });
		}

		//取消回调
		public unregister(notified: Function, context?: any): void {
			for (let i = 0; i < this.$registers.length; i++) {
				let register = this.$registers[i];
				let bingo = (!!context && register.context === context && register.notified === notified) || (!context && register.notified === notified);
				if (!bingo) continue;
				this.$registers.splice(i, 1); i--;
			}
		}
	}

	type Register = {
		notified: Function,
		every: number,
		times: number,
		context?: any,
	}
}
